﻿//using LightCAD.Help;
using LightCAD.Runtime;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LightCAD.UI
{
    public partial class CommandBar : UserControl, ICommandControl
    {
        private event Action<KeyEventRuntime> inputKeyDown;
        private event Action<KeyEventRuntime> inputKeyUp;
        private event Action<ICommandControl, EventArgs> inputGotFocus;
        private event Action<ICommandControl, EventArgs> inputLossFocus;
        private CommandInfo commandInfo;
        private HistoryCmdInfo historyCmdInfo;
        private CmdLogInfo cmdLogInfo;
        private List<string> allCommonds = new List<string>();
        private List<string> cmdHistory = new List<string>();
        private bool useAlternateCmdState = true; //是否启用备选命令区
        private string curCmd; //当前正在执行的命令
        private LcCreateMethod curMethod;
        private LcCreateStep curStep;

        public CommandBar()
        {
            InitializeComponent();
            this.AutoScaleMode = AutoScaleMode.None;
            this.commandInfo = CommandInfo.Instance;
            this.historyCmdInfo = HistoryCmdInfo.Instance;
            this.cmdLogInfo = CmdLogInfo.Instance;
            this.commandInfo.AttachExecuteAction((cmd) =>
            {
                this.txtInput.TextChanged -= txtInput_TextChanged;
                this.txtInput.Text = cmd;
                this.txtInput.TextChanged += txtInput_TextChanged;
                this.inputKeyDown?.Invoke(new KeyEventRuntime() { KeyCode = (int)Keys.Enter, KeyModifiers = LcKeyModifiers.None });
            });
            this.historyCmdInfo.AttachExecuteAction((cmd) =>
            {
                this.txtInput.TextChanged -= txtInput_TextChanged;
                this.txtInput.Text = cmd;
                this.txtInput.TextChanged += txtInput_TextChanged;
                this.inputKeyDown?.Invoke(new KeyEventRuntime() { KeyCode = (int)Keys.Enter, KeyModifiers = LcKeyModifiers.None });
            });
            this.txtInput.GotFocus += TxtInput_GotFocus;
            this.txtInput.LostFocus += TxtInput_LostFocus;
            this.txtInput.KeyDown += TxtInput_KeyDown;
            this.txtInput.KeyUp += TxtInput_KeyUp;

            this.btnCmdHis.LostFocus += btnCmdHis_LostFocus;
        }

        private void TxtInput_LostFocus(object? sender, EventArgs e)
        {
            inputLossFocus?.Invoke(this, e);
        }

        private void TxtInput_GotFocus(object? sender, EventArgs e)
        {
            inputGotFocus?.Invoke(this, e);
        }

        private void TxtInput_KeyUp(object? sender, KeyEventArgs e)
        {
            inputKeyUp?.Invoke(e.ToRuntime());
        }

        private void TxtInput_KeyDown(object? sender, KeyEventArgs e)
        {
            if (this.commandInfo.IsShow) //有备选命令
            {
                if (e.KeyCode == Keys.Up)
                {
                    this.commandInfo.Up();
                }
                if (e.KeyCode == Keys.Down)
                {
                    this.commandInfo.Down();
                }
                if (e.KeyCode == Keys.Enter)
                {
                    var cmd = this.commandInfo.GetCurrentCmd();
                    if (!string.IsNullOrEmpty(cmd))
                    {
                        this.txtInput.TextChanged -= txtInput_TextChanged;
                        this.txtInput.Text = cmd;
                        this.txtInput.TextChanged += txtInput_TextChanged;
                        this.inputKeyDown?.Invoke(new KeyEventRuntime() { KeyCode = (int)Keys.Enter, KeyModifiers = LcKeyModifiers.None });
                    }
                    this.curCmd = cmd;
                }
                return;
            }
            this.curCmd = null;
            inputKeyDown?.Invoke(e.ToRuntime());
        }

        private void btnCmdHis_LostFocus(object? sender, EventArgs e)
        {
            if (this.historyCmdInfo.IsShow)
            {
                //this.historyCmdInfo.Hide();
            }
        }

        public void AttachInputEvent(Action<KeyEventRuntime> onInputKeyDown, Action<KeyEventRuntime> onInputKeyUp, Action<ICommandControl, EventArgs> onInputGotFocus, Action<ICommandControl, EventArgs> onInputLossFocus)
        {
            this.inputKeyDown += onInputKeyDown;
            this.inputKeyUp += onInputKeyUp;
            this.inputGotFocus += onInputGotFocus;
            this.inputLossFocus += onInputLossFocus;
        }

        public void DetachInputEvent(Action<KeyEventRuntime> onInputKeyDown, Action<KeyEventRuntime> onInputKeyUp, Action<ICommandControl, EventArgs> onInputGotFocus, Action<ICommandControl, EventArgs> onInputLossFocus)
        {
            this.inputKeyDown -= onInputKeyDown;
            this.inputKeyUp -= onInputKeyUp;
            this.inputGotFocus -= onInputGotFocus;
            this.inputLossFocus -= onInputLossFocus;
        }

        public void SetAlternateCommandState(bool enabled)
        {
            this.useAlternateCmdState = enabled;
        }


        public void Prompt(string prompt)
        {
            this.lblPrompt.Text = prompt;
        }
        public string GetPrompt()
        {
            if (this.lblPrompt.Text == null || this.lblPrompt.Text.Length == 0)
                return "命令：";
            else
                return this.lblPrompt.Text;
        }
        public string GetInputText()
        {
            return this.txtInput.Text;
        }

        public void SetInputText(string str)
        {
            this.txtInput.Text = str;
        }

        public void WriteInfo(string info)
        {
            this.txtInfo.HideSelection = false;
            this.txtInfo.AppendText("\n" + info);
        }
        public string GetAllInfos()
        {
            return this.txtInfo.Text;
        }

        public void SetAllCommonds(List<string> cmds)
        {
            this.allCommonds = cmds;
        }

        private void txtInput_TextChanged(object sender, EventArgs e)
        {
            if (!this.useAlternateCmdState || this.allCommonds == null || this.allCommonds.Count == 0)
            {
                this.commandInfo.Hide();
                return;
            }

            string inputeTxt = this.txtInput.Text.ToUpper();
            if (string.IsNullOrEmpty(inputeTxt))
            {
                this.commandInfo.Hide();
                return;
            }

            var cmds = new List<string>();
            foreach (var cmd in this.allCommonds)
            {
                if (cmd.ToUpper().Contains(inputeTxt))
                {
                    cmds.Add(cmd);
                }
            }

            if (cmds == null || cmds.Count == 0)
            {
                this.commandInfo.Hide();
                return;
            }
            ShowCmdInfo(cmds);
        }

        bool isSHow;
        private void Test()
        {
            CommandInfo propForm = CommandInfo.Instance;
            if (isSHow)
            {
                propForm.Hide();
            }
            else
            {
            }
            isSHow = !isSHow;
        }

        private void ShowCmdInfo(List<string> cmds = null)
        {
            if (cmds != null)
            {
                this.commandInfo.SetValidCommonds(cmds);
            }
            var location = txtInput.PointToScreen(txtInput.Location);
            location.Y -= (commandInfo.frmPopup.Height + 10);


            if (!this.components.Components.OfType<ICommandInfoControl>().Any())
            {
                this.components.Add(this.commandInfo);
            }
            this.commandInfo.Show(location.X, location.Y);
        }

        private void ShowHistoryCmdInfo(List<string> cmds = null)
        {
            if (cmds != null)
            {
                this.historyCmdInfo.SetValidCommonds(cmds);
            }
            var location = btnCmdHis.PointToScreen(btnCmdHis.Location);
            location.X += 3;
            location.Y -= (historyCmdInfo.frmPopup.Height + 2);


            if (!this.components.Components.OfType<IHistoryCmdControl>().Any())
            {
                this.components.Add(this.historyCmdInfo);
            }
            this.historyCmdInfo.Show(location.X, location.Y);
        }

        private void ShowCmdLogInfo(string log)
        {
            this.cmdLogInfo.SetLog(log);

            var location = txtInput.PointToScreen(txtInput.Location);
            location.Y -= (cmdLogInfo.frmPopup.Height + 10);


            if (!this.components.Components.OfType<ICmdLogControl>().Any())
            {
                this.components.Add(this.commandInfo);
            }
            this.cmdLogInfo.Show(location.X, location.Y);
        }

        private bool isCollapsed;
        [DefaultValue(false)]
        public bool IsCollapsed
        {
            get { return isCollapsed; }
            set
            {
                if (isCollapsed != value)
                {
                    if (isCollapsed)
                    {
                        btnCollapse.Text = "▲";
                        btnCollapse_Click(null, null);
                    }
                    else
                    {
                        btnCollapse.Text = "▼";
                        btnCollapse_Click(null, null);
                    }
                }

            }
        }
        private void btnCollapse_Click(object sender, EventArgs e)
        {
            if (btnCollapse.Text == "▼")
            {
                this.Height = 30;
                btnCollapse.Text = "▲";
                isCollapsed = true;
            }
            else
            {
                this.Height = 84;
                btnCollapse.Text = "▼";
                isCollapsed = false;
            }
        }

        private void btnHelp_Click(object sender, EventArgs e)
        {
            //if (!string.IsNullOrEmpty(curCmd))
            //{
            //    //根据当前命令用Prop的方式显示帮助面板
            //    MessageBox.Show($"当前执行命令为：{curCmd};\r\n" +
            //                    $"当前执行方法为：{curMethod?.Description};\r\n" +
            //                    $"当前执行步骤为：{curStep?.Name}[{curStep?.Options}]");
            //}
            //HelpForm form = new HelpForm();
            //form.Show();
        }

        public void SetCurMethod(LcCreateMethod method)
        {
            this.curMethod = method;
        }

        public void SetCurStep(LcCreateStep step)
        {
            this.curStep = step;
        }

        private void btnCmdHis_Click(object sender, EventArgs e)
        {
            if (this.historyCmdInfo.IsShow)
            {
                this.historyCmdInfo.Hide();
            }
            else
            {
                ShowHistoryCmdInfo(this.cmdHistory);
            }
        }

        public void AddHistoryCmd(string cmd)
        {
            if (this.cmdHistory.Contains(cmd))
            {
                this.cmdHistory.Remove(cmd);
            }
            this.cmdHistory.Add(cmd);
            if (this.cmdHistory.Count > 0)
            {
                this.btnCmdHis.Enabled = true;
            }
        }

        private void btnLog_Click(object sender, EventArgs e)
        {
            if (this.cmdLogInfo.IsShow)
            {
                this.cmdLogInfo.Hide();
            }
            else
            {
                string log = this.txtInfo.Text;
                this.ShowCmdLogInfo(log);
            }
        }
    }
}
